/*
 * Copyright (C) 2009 Show SMS open source project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.bydavy.android.showsms.model;

//~--- non-JDK imports --------------------------------------------------------

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;

import android.net.Uri;

import android.os.Bundle;

import android.telephony.gsm.SmsMessage;

import android.text.format.DateFormat;

import com.bydavy.android.showsms.util.AppLog;
import com.bydavy.android.showsms.util.ShortMessageInfos;

//~--- JDK imports ------------------------------------------------------------

import java.util.Date;

//~--- classes ----------------------------------------------------------------

/**
 * Class that describe a <ShortMessage>
 * A message have a id (message id in the database), a thread id (conversation id in the database), a sender <contact>, a timeStamp (reception date) and a body
 *
 * @version        2.0, 10/03/07
 * @author         Davy L.
 */
public class ShortMessage implements Comparable<ShortMessage> {
    //~--- static fields ------------------------------------------------------

    public static final Uri SMS_CONTENT_URI           = Uri.parse("content://sms");
    public static final Uri SMS_OUTBOX_CONTENT_URI    = Uri.withAppendedPath(SMS_CONTENT_URI, "outbox");
    private static final int CONTENT_SMS_READED_VALUE = 1;
    public static final String EXTRAS_BODY            = "EXTRAS_MESSAGE_BODY";
    public static final String EXTRAS_ID              = "EXTRAS_MESSAGE_ID";
    public static final String EXTRAS_THREAD_ID       = "EXTRAS_MESSAGE_THREAD_ID";
    public static final String EXTRAS_TIMESTAMP       = "EXTRAS_MESSAGE_TIMESTAMP";

    //~--- fields -------------------------------------------------------------

    private long mId;
    private String mBody;
    private long mTimeStamp;

    //~--- constructors -------------------------------------------------------

    public ShortMessage(SmsMessage[] messages, Context context) {
        mTimeStamp = messages[0].getTimestampMillis();
        mId        = 0;
        mBody      = "";

        // Add body of each SMS
        for (int i = 0; i < messages.length; i++) {
            mBody += messages[i].getMessageBody();
        }
    }

    public ShortMessage(String body, long timeStamp) {
        mId        = 0;
        mBody      = body;
        mTimeStamp = timeStamp;

    }

    public ShortMessage(long id, String body, long timeStamp) {
        mId        = id;
        mBody      = body;
        mTimeStamp = timeStamp;
    }

    //~--- get methods --------------------------------------------------------

    public long getId() {
        return mId;
    }

    public String getBody() {
        return mBody;
    }

    public String getDate(Context context) {
        Date date = new Date(mTimeStamp);

        return DateFormat.getDateFormat(context).format(date);
    }

    public long getHour() {
        return mTimeStamp;
    }

    public String getHourFormatted(Context context) {
        Date date = new Date(mTimeStamp);

        return DateFormat.getTimeFormat(context).format(date);
    }

    // Get date or hour if mTimeStamp less than 24h
    public String getHourOrDate(Context c) {
        long currTime = System.currentTimeMillis();

        if ((currTime - mTimeStamp) < 360000) {
            return getHourFormatted(c);
        }

        return getDate(c) + " " + getHourFormatted(c);
    }

    //~--- methods ------------------------------------------------------------

    public static ShortMessage constructFromBundle(Bundle bundle) {
        return constructFromBundle(bundle, "");
    }

    public static ShortMessage constructFromBundle(Bundle bundle, String num) {
        long id        = bundle.getLong(EXTRAS_ID + num);
        long timeStamp = bundle.getLong(EXTRAS_TIMESTAMP + num);
        String body    = bundle.getString(EXTRAS_BODY + num);

        return new ShortMessage(id, body, timeStamp);
    }

    public Bundle toBundle(Bundle b) {
        return toBundle(b, "");
    }

    public Bundle toBundle(Bundle b, String num) {
        b.putLong(EXTRAS_ID + num, mId);
        b.putLong(EXTRAS_TIMESTAMP + num, mTimeStamp);
        b.putString(EXTRAS_BODY + num, mBody);

        return b;
    }

    public Bundle toBundle() {
        return toBundle(new Bundle());
    }

    @Override
    public String toString() {
        StringBuffer buff = new StringBuffer("id : " + mId);

        buff.append(", timeStamp : " + mTimeStamp);
        buff.append(", body : " + mBody);

        return buff.toString();
    }

    /**
     * Mark the current <ShortMessage> as readed in the database
     * The mark as read status is simply updated, so this method can be called several times (return true each time)
     * @param context application context
     *
     * @return true if mark as read status was write successfully, otherwise false (error occured)
     */
    public boolean markAsRead(Context context) {
        if (markAsReadAMessage(mId, context) != 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Mark the as readed in the database the message that as the id <message_id>
     * The mark as read status is simply updated, so this method can be called several times
     *
     * @param message_id message id of the message to mark as readed
     * @param context application context
     *
     * @return 0 if the make as read status wasn't updated, otherwise return a positive integer
     */
    private static int markAsReadAMessage(long message_id, Context context) {
        Uri messageUri       = ContentUris.withAppendedId(SMS_CONTENT_URI, message_id);
        ContentValues values = new ContentValues(1);

        values.put("read", CONTENT_SMS_READED_VALUE);

        int result = 0;

        try {
            result = context.getContentResolver().update(messageUri, values, null, null);
        } catch (Exception e) {
            AppLog.v("Error during setting message readed");
        }

        AppLog.v("ShortMessage " + message_id + " marked as read, result = " + result);

        return result;
    }

    public void delete(Context context) {
        Uri uri = ContentUris.withAppendedId(SMS_CONTENT_URI, mId);

        context.getContentResolver().delete(uri, null, null);
    }

    public void updateShortMessage(long threadId, Context context) {
        if (mId == 0) {
            mId = ShortMessageInfos.findId(threadId, mBody, context);
        }
    }

    @Override
    public int compareTo(ShortMessage another) {
        return (int) (mTimeStamp - another.mTimeStamp);
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }

        if (!(o instanceof ShortMessage)) {
            return false;
        }

        ShortMessage s = (ShortMessage) o;

        return mId == s.mId;
    }

    public int hashCode() {
        return (int) mId;
    }
}
